package com.compomics.prioritizer.general;

import javax.swing.*;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.awt.event.*;
import java.awt.*;
import java.util.Properties;
import java.io.InputStream;

/**
 * Created by IntelliJ IDEA.
 * User: Niklaas Colaert
 * Date: 6-nov-2008
 * Time: 7:55:52
 * To change this template use File | Settings | File Templates.
 */
public class ConnectionDialog  extends JDialog {

    private Connection lConnPriority = null;

    private ConnectablePriorityProject iTarget = null;

    private JTextField txtDriver = null;
    private JTextField txtUrl = null;
    private JTextField txtUser = null;
    private JPasswordField txtPassword = null;
    private JLabel driverLbl = new JLabel();
    private JLabel databaseLbl = new JLabel();
    private JLabel usernameLbl = new JLabel();
    private JLabel passwordLbl = new JLabel();

    private JButton btnOK = null;
    private JButton btnCancel = null;
    private String iPropsFile;

    public ConnectionDialog(JFrame aParent, ConnectablePriorityProject aTarget,  String title, String aPropsFile) {
        super(aParent, title, true);

        this.iTarget = aTarget;
        this.iPropsFile = aPropsFile;
        // Initialize frame.

        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent evt) {
                close();
            }
        });
        constructScreen();

        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (d.width - getSize().width) / 3;
        int y = (d.height - getSize().height) / 3;
        setLocation(x, y);
        setResizable(false);
        this.pack();


        tryToLoadParams();

    }

    private void constructScreen() {



        txtDriver = new JTextField(25);
        txtDriver.addKeyListener(new KeyAdapter() {
        /**
        * Invoked when a key has been typed.
        * This event occurs when a key press is followed by a key release.
        */
        public void keyTyped(KeyEvent e) {
          if(e.getKeyChar() == KeyEvent.VK_ENTER) {
          txtUrl.requestFocus();
             } else {
                super.keyTyped(e);
             }
          }
        });

        txtUrl = new JTextField(25);
        txtUrl.addKeyListener(new KeyAdapter() {
            /**
             * Invoked when a key has been typed.
             * This event occurs when a key press is followed by a key release.
             */
            public void keyTyped(KeyEvent e) {
                if(e.getKeyChar() == KeyEvent.VK_ENTER) {
                    txtUser.requestFocus();
                } else {
                    super.keyTyped(e);
                }
            }
        });


        txtUser = new JTextField(25);
        txtUser.addKeyListener(new KeyAdapter() {
            /**
             * Invoked when a key has been typed.
             * This event occurs when a key press is followed by a key release.
             */
            public void keyTyped(KeyEvent e) {
                if(e.getKeyChar() == KeyEvent.VK_ENTER) {
                    txtPassword.requestFocus();
                } else {
                    super.keyTyped(e);
                }
            }
        });

        txtPassword = new JPasswordField(25);
        txtPassword.addKeyListener(new KeyAdapter() {
            /**
             * Invoked when a key has been typed.
             * This event occurs when a key press is followed by a key release.
             */
            public void keyTyped(KeyEvent e) {
                if(e.getKeyChar() == KeyEvent.VK_ENTER) {
                    txtDriver.requestFocus();;
                } else {
                    super.keyTyped(e);
                }
            }
        });

        JPanel jpanDriver = new JPanel();
        jpanDriver.setLayout(new BoxLayout(jpanDriver, BoxLayout.X_AXIS));
        jpanDriver.add(txtDriver);
        jpanDriver.add(Box.createHorizontalGlue());

        JPanel jpanUrl = new JPanel();
        jpanUrl.setLayout(new BoxLayout(jpanUrl, BoxLayout.X_AXIS));
        jpanUrl.add(txtUrl);
        jpanUrl.add(Box.createHorizontalGlue());

        JPanel jpanUser = new JPanel();
        jpanUser.setLayout(new BoxLayout(jpanUser, BoxLayout.X_AXIS));
        jpanUser.add(txtUser);
        jpanUser.add(Box.createHorizontalGlue());

        JPanel jpanPassword = new JPanel();
        jpanPassword.setLayout(new BoxLayout(jpanPassword, BoxLayout.X_AXIS));
        jpanPassword.add(txtPassword);
        jpanPassword.add(Box.createHorizontalGlue());

        JPanel jpanFields = new JPanel();
        jpanFields.setLayout(new BoxLayout(jpanFields, BoxLayout.Y_AXIS));
        jpanFields.add(jpanDriver);
        jpanFields.add(Box.createVerticalStrut(5));
        jpanFields.add(jpanUrl);
        jpanFields.add(Box.createVerticalStrut(5));
        jpanFields.add(jpanUser);
        jpanFields.add(Box.createVerticalStrut(5));
        jpanFields.add(jpanPassword);
        jpanFields.add(Box.createVerticalGlue());

        driverLbl.setText("Database driver  :");
        driverLbl.setPreferredSize(new Dimension(driverLbl.getPreferredSize().width, jpanDriver.getPreferredSize().height));

        databaseLbl.setText("Database URL  :");
        databaseLbl.setPreferredSize(new Dimension(databaseLbl.getPreferredSize().width, jpanUrl.getPreferredSize().height));

        usernameLbl.setText("Username  :");
        usernameLbl.setPreferredSize(new Dimension(usernameLbl.getPreferredSize().width, jpanUser.getPreferredSize().height));


        passwordLbl.setText("Password  :");
        passwordLbl.setPreferredSize(new Dimension(passwordLbl.getPreferredSize().width, jpanPassword.getPreferredSize().height));

        JPanel jpanLabels = new JPanel();
        jpanLabels.setLayout(new BoxLayout(jpanLabels, BoxLayout.Y_AXIS));
        jpanLabels.add(driverLbl);
        jpanLabels.add(Box.createVerticalStrut(10));
        jpanLabels.add(databaseLbl);
        jpanLabels.add(Box.createVerticalStrut(10));
        jpanLabels.add(usernameLbl);
        jpanLabels.add(Box.createVerticalStrut(10));
        jpanLabels.add(passwordLbl);
        jpanLabels.add(Box.createVerticalStrut(10));


        // This panel holds the connection details labels and textfields.
        JPanel jpanConnectionDetails = new JPanel();
        jpanConnectionDetails.setLayout(new BoxLayout(jpanConnectionDetails, BoxLayout.X_AXIS));
        jpanConnectionDetails.setBorder(BorderFactory.createTitledBorder("Prioritizer connection details"));
        jpanConnectionDetails.add(jpanLabels);
        jpanConnectionDetails.add(Box.createHorizontalStrut(15));
        jpanConnectionDetails.add(jpanFields);

        btnOK = new JButton("Connect");
        btnOK.setMnemonic(KeyEvent.VK_O);
        btnOK.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                connectTriggered();
            }
        });
        btnOK.addKeyListener(new KeyAdapter() {
            /**
             * Invoked when a key has been typed.
             * This event occurs when a key press is followed by a key release.
             */
            public void keyTyped(KeyEvent e) {
                if(e.getKeyChar() == KeyEvent.VK_ENTER) {
                    connectTriggered();
                }
            }
        });
        btnCancel = new JButton("Cancel");
        btnCancel.setMnemonic(KeyEvent.VK_C);
        btnCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                cancelTriggered();
            }
        });
        btnCancel.addKeyListener(new KeyAdapter() {
            /**
             * Invoked when a key has been typed.
             * This event occurs when a key press is followed by a key release.
             */
            public void keyTyped(KeyEvent e) {
                if(e.getKeyChar() == KeyEvent.VK_ENTER) {
                    cancelTriggered();
                }
            }
        });

        JPanel jpanButtons = new JPanel();
        jpanButtons.setLayout(new BoxLayout(jpanButtons, BoxLayout.X_AXIS));

        jpanButtons.add(Box.createHorizontalGlue());
        jpanButtons.add(btnCancel);
        jpanButtons.add(Box.createRigidArea(new Dimension(10, btnOK.getHeight())));
        jpanButtons.add(btnOK);
        jpanButtons.add(Box.createRigidArea(new Dimension(15, btnOK.getHeight())));


        JPanel jpanTotal = new JPanel();
        jpanTotal.setLayout(new BoxLayout(jpanTotal, BoxLayout.Y_AXIS));
        jpanTotal.add(jpanConnectionDetails);
        jpanTotal.add(jpanButtons);

        this.getContentPane().add(jpanTotal, BorderLayout.CENTER);

    }

    private void connectTriggered() {
        String driverClass = txtDriver.getText().trim();
        String url = txtUrl.getText().trim();
        String user = txtUser.getText().trim();
        String password = new String(txtPassword.getPassword()).trim();

        if(driverClass.equals("")) {
            JOptionPane.showMessageDialog(this, "Driver class needs to be specified!", "No driver specified for priority!", JOptionPane.ERROR_MESSAGE);
            txtDriver.requestFocus();
            return;
        }

        if(url.equals("")) {
            JOptionPane.showMessageDialog(this, "Database URL needs to be specified!", "No URL specified for priority!", JOptionPane.ERROR_MESSAGE);
            txtUrl.requestFocus();
            return;
        }

        String errorString = null;

        try {
            this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
            Driver d = (Driver)Class.forName(driverClass).newInstance();
            Properties lProps = new Properties();
            if(user != null) {
                lProps.put("user", user);
            }
            if(password != null) {
                lProps.put("password", password);
            }
            lConnPriority = d.connect(url, lProps);
            if(lConnPriority == null) {
                errorString = "Could not connect to the database priority. Either your driver is incorrect for this database, or your URL is malformed.";
            }
        } catch(ClassNotFoundException cnfe) {
            errorString = "Driver class was not found! (" + cnfe.getMessage() + ")";
        } catch(IllegalAccessException iae) {
            errorString = "Could not access default constructor on driver class! (" + iae.getMessage() + ")";
        } catch(InstantiationException ie) {
            errorString = "Could not create instance of driver class! (" + ie.getMessage() + ")";
        } catch(SQLException sqle) {
            errorString = "Database refused connection! (" + sqle.getMessage() + ")";
        }

        this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        if(errorString != null) {
            JOptionPane.showMessageDialog(this, new String[]{"Unable to make the connection to '" + url + "' using '" + driverClass + "'!", errorString, "\n"}, "Unable to connect!", JOptionPane.ERROR_MESSAGE);
            return;
        } else {
            JOptionPane.showMessageDialog(this, new String[]{"Connection to '" + url + "' established!", "\n"}, "Connection established!", JOptionPane.INFORMATION_MESSAGE);
            iTarget.passConnectionPriority(lConnPriority);
            this.setVisible(false);
            this.dispose();
        }


     }



    private void cancelTriggered() {
        System.exit(0);

    }

    private void close() {
        System.exit(0);
    }
    /**
     * This method attempts to load connection parameters from
     * a properties file in the classpath.
     * If this file is not found, nothing happens.
     * If it is found, the parameters found will be filled out.
     */
    private void tryToLoadParams() {
        if(iPropsFile != null) {
            try {
                Properties p = new Properties();
                InputStream is = ClassLoader.getSystemResourceAsStream(iPropsFile);
                if(is == null) {
                    is = this.getClass().getClassLoader().getResourceAsStream(iPropsFile);
                    if(is == null) {
                        // Leave it at that.
                        System.out.println("No properties file found!");
                        return;
                    }
                    System.out.println("local classloader.");
                }
                p.load(is);
                String dbDriver = p.getProperty("driver");
                if(dbDriver == null) {
                    dbDriver = p.getProperty("DRIVER");
                }
                String dbUrl = p.getProperty("url");
                if(dbUrl == null) {
                    dbUrl = p.getProperty("URL");
                }
                String dbUser = p.getProperty("user");
                if(dbUser == null) {
                    dbUser = p.getProperty("USER");
                }
                if(dbDriver != null) {
                    this.txtDriver.setText(dbDriver.trim());
                }
                if(dbUrl != null) {
                    this.txtUrl.setText(dbUrl.trim());
                }
                if(dbUser != null) {
                    this.txtUser.setText(dbUser.trim());
                }
                is.close();
            } catch(Exception e) {
                // Do nothing.
                e.printStackTrace();
            }
        }
    }
}
